contents
๐ก ์ฝ๋ฉ ํ ์คํธ๋ฅผ ์ํ ๋นํธ ์ฐ์ฐ(Bit Manipulation) ๊ฐ์ด๋ ๋ฐ ์์
๋นํธ ์ฐ์ฐ์ ๋น ๋ฅธ ๊ณ์ฐ(O(1)), ๊ณต๊ฐ ์ ์ฝ, ํน์ ์๊ณ ๋ฆฌ์ฆ/์ต์ ํ์์ ๋งค์ฐ ์ ์ฉํ๋ฉฐ, ์ฝ๋ฉ ํ ์คํธ์ ๋ฉด์ ์์ ์์ฃผ ์ถ์ ๋ฉ๋๋ค.
1. ๋นํธ ์ฐ์ฐ์ ๊ธฐ๋ณธ ๊ฐ๋
- ๋นํธ ์ฐ์ฐ์ ์ ์์ ์ด์ง์(๋นํธ) ๋จ์๋ก ์ง์ AND, OR, XOR, SHIFT ๋ฑ์ ์ํํ๋ ๊ธฐ๋ฒ์ ๋๋ค.
- ์ฅ์ : ๋งค์ฐ ๋น ๋ฅธ ์ฐ์ฐ, ์ต์ ํ/ํน์ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํ์ ํ์
- ํ์ฉ: ํ/์ง ํ๋ณ, ์งํฉ, ๋นํธ ํ ๊ธ, ์ ์ผ๊ฐ ์ฐพ๊ธฐ, ๋ถ๋ถ์งํฉ ์์ฑ ๋ฑ
2. ์์ฃผ ์ฐ๋ ๋นํธ ์ฐ์ฐ์
| ์ฐ์ฐ์ | ๊ธฐํธ | ๊ธฐ๋ฅ | ์์ | ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| AND | & | ๋นํธ ๋จ์ AND | 5 & 3 โ 0101 & 0011 | 0001(1) |
| OR | | | ๋นํธ ๋จ์ OR | 5 | 3 | 0111(7) |
| XOR | ^ | ๋นํธ ๋จ์ XOR | 5 ^ 3 | 0110(6) |
| NOT | ~ | ๋นํธ ๋ฐ์ (๋ชจ๋ ๋นํธ ๋ค์ง์) | ~5 | ... |
| ์ผ์ชฝ ์ํํธ | << | n๋งํผ ์ผ์ชฝ ์ด๋ | 3 << 2 (0011โ1100) | 12 |
| ์ค๋ฅธ์ชฝ ์ํํธ | >> | n๋งํผ ์ค๋ฅธ์ชฝ ์ด๋ | 8 >> 2 (1000โ0010) | 2 |
3. ๋นํธ ์ฐ์ฐ ๊ธฐ๋ณธ ํธ๋ฆญ
a. ํ์/์ง์ ํ๋ณ
x % 2 == 0โ(x & 1) == 0- ํ์๋ ๋ง์ง๋ง ๋นํธ๊ฐ 1, ์ง์๋ 0
b. ๋ ์ ์ค์(XOR ์ค์)
a ^= b;
b ^= a;
a ^= b;
(์์๋ณ์ ์์ด ๊ฐ๋ฅ)
c. k๋ฒ์งธ ๋นํธ ์ค์ /ํด์ /ํ ๊ธ
- ์ค์ (Set):
x |= (1 << k) - ํด์ (Clear):
x &= ~(1 << k) - ํ ๊ธ(Toggle):
x ^= (1 << k)
4. ๋นํธ ์นด์ดํธ ๋ฐ ์์น ํ์
a. ์ค์ ๋ ๋นํธ ๊ฐ์ ์ธ๊ธฐ(Kernighan ์๊ณ ๋ฆฌ์ฆ)
int countBits(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1);
count++;
}
return count;
}
์ค์ ๋ ๋นํธ๋ฅผ ํ๋์ฉ ์ ๊ฑฐ
b. k๋ฒ์งธ ๋นํธ ์ถ์ถ
int getKthBit(int n, int k) {
return (n >> k) & 1;
}
c. ๊ฐ์ฅ ๋ฎ์ ์ค์ ๋นํธ ์ถ์ถ
int lowestBit = n & -n;
(์ตํ์ 1๋นํธ๋ง ๋จ๊น)
5. ๋นํธ๋ง์คํฌ(Bitmask)๋ฅผ ์ด์ฉํ ๋ถ๋ถ์งํฉ/์ํ ํํ
- n๊ฐ ์์์ ๋ชจ๋ ๋ถ๋ถ์งํฉ โ 0~(1<<n)-1๊น์ง ๋นํธ๋ง์คํฌ๋ก ํํ
- ๊ฐ ๋นํธ์ ์์น๊ฐ ์์ ํฌํจ ์ฌ๋ถ๋ฅผ ์๋ฏธ
๋ถ๋ถ์งํฉ ์์ฑ ์์:
for (int mask = 0; mask < (1 << n); mask++) {
for (int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 1) {
// i๋ฒ์งธ ์์ ํฌํจ
}
}
}
6. ๋ํ ๋นํธ ๋ฌธ์
a. ์์ด์์ ํ ๋ฒ๋ง ๋ํ๋๋ ์์ ์ฐพ๊ธฐ (Single Number)
int unique = 0;
for (int num : arr)
unique ^= num;
return unique;
(XOR๋ก ์ค๋ณต ์ ๊ฑฐ, ๋จ์ผ ์์๋ง ๋จ์)
b. ํ์ ๋ฒ ๋ฑ์ฅ ์์ ์ฐพ๊ธฐ
- ์ XOR ํธ๋ฆญ๊ณผ ๋์ผ
c. 2์ ๊ฑฐ๋ญ์ ๊ณฑ ํ๋ณ
boolean isPowerOf2(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
(1๋นํธ๋ง ์ค์ ๋ ์)
d. Sieve(์๋ผํ ์คํ ๋ค์ค ๋ฑ)์ ๋นํธ๋ง์คํฌ ํ์ฉ
- ๋ฐฐ์ด ๋์ ์ ์์ ๋นํธ๋ฅผ flag๋ก ์ฌ์ฉํด ๊ณต๊ฐ ์ ์ฝ
7. ๋ฉด์ /์ฝํ ์์์ ํจํด๋ณ ํ์ฉ
| ์์ | ๋ํ ๋นํธ ํธ๋ฆญ |
|---|---|
| ๋ถ๋ถ์งํฉยท์กฐํฉ ์์ฑ | 0 ~ (2^n)-1 ๋นํธ๋ง์คํฌ ๋ฐ๋ณต |
| ๋น ๋ฅธ ์งํฉ ๋ฉค๋ฒ์ญ | ๋นํธ๋ง์คํฌ ํ์ฉ (Set ํจ๊ณผ) |
| ์ ์ผ๊ฐยท๋น๋ ์นด์ดํธ | XOR, ๋นํธ ์นด์ดํธ |
| ๋น ๋ฅธ ์ํ์ฐ์ฐ | ์ํํธยทAND/OR๋ก ๊ณฑ์ ยท๋๋์ |
| DP/๊ฒ์ ์ํ ์์ถ | ๋นํธ๋ง์คํฌ DP, ์ํ ํํ |
8. ๊ณ ๊ธ ๋นํธ ํธ๋ฆญ
- ๋นํธ ๋ฐ์ (reverse), ๋น ๋ฅธ popcount
- ๋นํธ๋ง์คํฌ์ ๋ค์ ์์ด(Gosperโs hack)
- Gray ์ฝ๋ ์์ฑ
- ์ต๊ณ /์ต์ 1๋นํธ ์์น ์ก๊ธฐ
9. ์ค์/์ฃผ์ ์ฌํญ
- ๋ถํธ๊ฐ ์๋ ์ ์์ ์ํํธยท์ฐ์ฐ ์ ์ฃผ์(ํนํ ์์)
- NOT(~) ์ฐ์ฐ์ ๋ถํธ ๋ฐ์ , ํ์ ์กฐ์ฌ
- ๋ฎ์ ์์ค ๋นํธ ์ฐ์ฐ์ unsigned ํ์ ์ด๋ C++/Python ์ฌ์ฉ์ ๋ ์์ ๋ก์
10. ์์ฝ ํ โ ๋นํธ ์ฐ์ฐ ์ฝ๋ฉ ์ํ ํจํด
| ํจํด | ์์ ์ฝ๋/ํํ |
|---|---|
| k๋ฒ์งธ ๋นํธ ์ฒดํฌ | (n >> k) & 1 |
| k๋ฒ์งธ ๋นํธ ์ค์ | n |
| k๋ฒ์งธ ๋นํธ ํด์ | n &= ~(1 << k) |
| XOR ์ค์ | a ^= b; b ^= a; a ^= b; |
| ๋นํธ์นด์ดํธ | while (n != 0) {n &= (n-1); count++;} |
| 2์ ๊ฑฐ๋ญ์ ๊ณฑ ์ฒดํฌ | n > 0 && (n & (n-1)) == 0 |
| ๋จ์ผ๊ฐ ์ฐพ๊ธฐ(XOR) | ans ^= arr[i] |
| ๋ถ๋ถ์งํฉ ์ด๊ฑฐ | mask: 0 ~ (1<<n)-1 |
๐ก ๋นํธ ์ฐ์ฐ ์ฝ๋ฉ ํ ์คํธ ๋ํ ๋น์ถ ๋ฌธ์ & ํ์ด/ํธ๋ฆญ ์ ๋ฆฌ
์๋๋ ์ฝ๋ฉ ํ ์คํธ์ ๋ฉด์ ์์ ๊ฐ์ฅ ์์ฃผ ์ถ์ ๋๋ ๋นํธ ์ฐ์ฐ ๋ฌธ์ ์ ๊ธฐ๋ณธ ์๋ฃจ์ ๋ฐ ํต์ฌ ์์ด๋์ด์ ๋๋ค.
1. Single Number (ํ ๋ฒ๋ง ๋ฑ์ฅํ๋ ์ ์ฐพ๊ธฐ)
๋ฌธ์ :
์ ์ ๋ฐฐ์ด์์, ๋ชจ๋ ์ซ์๊ฐ ๋ ๋ฒ์ฉ ๋ฑ์ฅํ์ง๋ง ์ค์ง ํ๋๋ง ํ ๋ฒ๋ง ๋ฑ์ฅํฉ๋๋ค. ๊ทธ ์ซ์๋ฅผ ์ฐพ์ผ์ธ์.
ํ์ด:
๋ชจ๋ ์ซ์๋ฅผ XORํ๋ฉด, ์ง์ ๊ฐ๋ ์๊ฑฐ๋์ด ๋จ์ผ ์ซ์๋ง ๋จ์.
int singleNumber(int[] nums) {
int res = 0;
for (int num : nums) res ^= num;
return res;
}
2. Two Single Numbers (๋ ๋ฒ ๋ฑ์ฅํ์ง ์๋ ์ 2๊ฐ ์ฐพ๊ธฐ)
๋ฌธ์ :
๋ฐฐ์ด์ ํ ๋ฒ๋ง ๋ฑ์ฅํ๋ ์๊ฐ ์ ํํ 2๊ฐ, ๋๋จธ์ง๋ ๋ชจ๋ ๋ ๋ฒ์ฉ. ๋ ๋ค ์ฐพ์๋ณด์ธ์.
ํ์ด:
์ ์ฒด XORํ๋ฉด x^y๊ฐ ๋์ด. ์ค๋ฅธ์ชฝ ์ฒซ 1๋นํธ๋ก ๊ทธ๋ฃน์ ๋๋ ๋ค์ XOR.
int xor = 0;
for (int num : nums) xor ^= num;
int mask = xor & -xor;
int x = 0, y = 0;
for (int num : nums) {
if ((num & mask) == 0) x ^= num;
else y ^= num;
}
// x์ y๊ฐ ๋ต
3. 1 ๋นํธ ๊ฐ์ ์ธ๊ธฐ (Hamming Weight)
๋ฌธ์ :
์ ์ ์ด์ง์ ํํ์์ 1์ ๊ฐ์๋ฅผ ์ธ์ด๋ผ.
ํ์ด:
Brian Kernighan ์๊ณ ๋ฆฌ์ฆ
int hammingWeight(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1);
count++;
}
return count;
}
4. 2์ ๊ฑฐ๋ญ์ ๊ณฑ ํ๋ณ
๋ฌธ์ :
์ ์๊ฐ 2์ ๊ฑฐ๋ญ์ ๊ณฑ์ธ์ง ์ฒดํฌํ์ธ์ (๋จ ํ๋์ 1๋นํธ).
ํ์ด:
boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
5. ๋ถ๋ถ์งํฉ ์์ฑ(Bitmask ํ์ฉ)
๋ฌธ์ :
์ฃผ์ด์ง ์งํฉ์ ๋ชจ๋ ๋ถ๋ถ์งํฉ์ ์ถ๋ ฅํ์ธ์.
ํ์ด:
for (int mask = 0; mask < (1 << n); mask++) {
for (int i = 0; i < n; i++) {
if ((mask & (1 << i)) != 0) {
// i๋ฒ์งธ ์์ ํฌํจ
}
}
}
6. Missing Number (0~n, ํ๋๋ง ์๋ ์ ์ฐพ๊ธฐ)
๋ฌธ์ :
0~n๊น์ง์ ์๊ฐ ํ๋๋ง ๋น ์ง ๋ฐฐ์ด์์, ๋น ์ง ์ซ์๋ฅผ ์ฐพ์ผ์ธ์.
ํ์ด:
๋ฐฐ์ด ์ ์ฒด XOR + ์ธ๋ฑ์ค XOR + n ๊ฐ โ ์ ๋ต
int missingNumber(int[] nums) {
int res = 0;
int n = nums.length;
for (int i = 0; i < n; i++) res ^= nums[i] ^ i;
return res ^ n;
}
7. ๋นํธ ๋ค์ง๊ธฐ (Reverse Bits)
๋ฌธ์ :
32๋นํธ ์ซ์์ ๋นํธ ์์๋ฅผ ๋ฐ์ ํ์ธ์.
ํ์ด:
int reverseBits(int n) {
int res = 0;
for (int i = 0; i < 32; i++) {
res = (res << 1) | (n & 1);
n >>= 1;
}
return res;
}
8. ๋ ์ ์ค์ (๋นํธ๋ง์ผ๋ก ์์ ์์ด ๊ตํ)
๋ฌธ์ :
a์ b๋ฅผ ์์ ๋ณ์ ์์ด ์ค์ํ์ธ์.
ํ์ด:
a ^= b; b ^= a; a ^= b;
9. k๋ฒ์งธ ๋นํธ Setting/Clearing/Toggling
๋ฌธ์ :
์ ์ n์์ k๋ฒ์งธ ๋นํธ๋ฅผ ์ค์ /ํด์ /ํ ๊ธํ์ธ์.
ํ์ด:
// ์ค์
n |= (1 << k);
// ํด์
n &= ~(1 << k);
// ํ ๊ธ
n ^= (1 << k);
์์ฝ ํ
| ๋ฌธ์ ์ ํ | ํต์ฌ ๋นํธ ํธ๋ฆญ/์ฝ๋ |
|---|---|
| ๋จ์ผ๊ฐ ์ฐพ๊ธฐ | XOR ์ ์ฒด |
| ๋ ๋จ์ผ๊ฐ ์ฐพ๊ธฐ | XORโ๋ง์คํฌ๋ก ๊ทธ๋ฃน ๋ถ๋ฆฌ |
| 1 ๋นํธ ๊ฐ์ | n &= (n-1) ๋ฐ๋ณต |
| 2์ ๊ฑฐ๋ญ์ ๊ณฑ ํ๋ณ | n > 0 && (n & (n-1)) == 0 |
| ๋ถ๋ถ์งํฉ ์์ฑ | mask: 0 ~ (1<<n)-1 |
| ๋น ์ง ์ซ์ ์ฐพ๊ธฐ | XOR(index+๋ฐฐ์ด+n) |
| ๋นํธ ๋ค์ง๊ธฐ | shift+OR ๋ฐ๋ณต |
| Swap ๋ฌด์์ | a ^= b โ b ^= a โ a ^= b |
| ๋นํธ ์ค์ /ํด์ /ํ ๊ธ | n |
references